"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 系统内部使用工具
Case Name   : 同一主机build该主机不同端口级联备
Create At   : 2022/06/08
Owner       : opentestcase023
Description :
    1.备1节点初始化数据库
    2.备1节点配置guc参数
    3.级联备配置guc参数
    4.build级联备并查询级联备情况
    5.清理环境
Expect      :
    1.数据库初始化成功
    2.备1guc参数配置成功
    3.级联备guc参数配置成功
    4.build成功，级联备显示正常
    5.环境清理成功
History     :
"""
import os
import time
import unittest

from yat.test import Node
from yat.test import macro

from testcase.utils.Common import Common
from testcase.utils.Common import CommonSH
from testcase.utils.Logger import Logger

primary_sh = CommonSH('PrimaryDbUser')


@unittest.skipIf(3 != primary_sh.get_node_num(), '非1+2环境不执行')
class Tools(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.common = Common()
        self.log.info(f'----{os.path.basename(__file__)} start----')
        self.standby1_root_node = Node('Standby1Root')
        self.standby1_node = Node('Standby1DbUser')
        self.sta1_comsh = CommonSH('Standby1DbUser')
        self.sta1_host = self.standby1_node.ssh_host
        self.port = self.standby1_node.db_port
        self.dn_path = os.path.join(os.path.dirname(macro.DB_INSTANCE_PATH),
                                    'dn_path')
        self.conf_path = os.path.join(macro.DB_INSTANCE_PATH,
                                      macro.DB_PG_CONFIG_NAME)

    def test_gs_ctl(self):
        text = '----step1:在备1执行init数据库 expect:成功----'
        self.log.info(text)
        mkdir_cmd = f'rm -rf {self.dn_path};' \
                    f'mkdir {self.dn_path};ls {os.path.dirname(self.dn_path)}'
        self.log.info(mkdir_cmd)
        dir_res = self.common.get_sh_result(self.standby1_node, mkdir_cmd)
        self.assertIn('dn_path', dir_res, '文件夹创建失败')

        init_cmd = f'source {macro.DB_ENV_PATH};' \
                   f'gs_initdb {self.dn_path} -w"{macro.COMMON_PASSWD}" ' \
                   f'--nodename=single'
        self.log.info(init_cmd)
        init_res = self.common.get_sh_result(self.standby1_node, init_cmd)
        self.assertIn('Success', init_res, 'init失败')

        text = '----step2:在备1节点配置guc参数 expect:成功----'
        self.log.info(text)
        text = '----查看主机名----'
        self.log.info(text)
        global sta1_nodename
        sta1_nodename = self.common.get_sh_result(self.standby1_root_node,
                                                  "uname -n")
        self.assertIsNotNone(sta1_nodename, '执行失败:' + text)

        local_port = int(self.port) + 1
        localheartbeatport = int(self.port) + 5
        localservice = int(self.port) + 4
        for num in range(10):
            flag = 0
            new_port = self.common.get_not_used_port(self.standby1_node)
            self.log.info(new_port)
            self.assertNotEqual(0, new_port, '端口为0')
            remote_port = int(new_port) + 1
            remoteheartbeatport = int(new_port) + 5
            remoteservice = int(new_port) + 4
            port_lis = [remote_port, remoteheartbeatport, remoteservice]
            self.log.info(port_lis)
            for port in port_lis:
                check_res = self.standby1_root_node.sh(
                    f'netstat -tlnp | grep {port}').result()
                self.log.info(check_res)
                if check_res:
                    flag = 1
                    break
            if flag == 1:
                continue
            else:
                break
        global slot_name
        slot_name = f'single_{self.sta1_host}_{remote_port}'
        self.log.info(slot_name)
        guc_cmd = f'source {macro.DB_ENV_PATH};' \
                  f'gs_guc reload -D {macro.DB_INSTANCE_PATH} ' \
                  f'-N {sta1_nodename} -c ' \
                  f'"replconninfo3 = \'localhost={self.sta1_host} ' \
                  f'localport={local_port} ' \
                  f'localheartbeatport={localheartbeatport} ' \
                  f'localservice={localservice} ' \
                  f'remotehost={self.sta1_host} ' \
                  f'remoteport={remote_port} ' \
                  f'remoteheartbeatport={remoteheartbeatport} ' \
                  f'remoteservice={remoteservice}\'"'
        self.log.info(guc_cmd)
        guc_res = self.common.get_sh_result(self.standby1_node, guc_cmd)
        self.assertIn('Success to perform gs_guc', guc_res, 'guc设置失败')

        text = '----step3:在级联备机配置guc参数 expect:成功----'
        self.log.info(text)
        az_cmd = f'cat {self.conf_path} | grep AZ'
        self.log.info(az_cmd)
        available_zone = self.common.get_sh_result(self.standby1_node,
                                                   az_cmd).split('\'')[-2]
        guc_cmd1 = f'source {macro.DB_ENV_PATH};' \
                   f'gs_guc set -D {self.dn_path} ' \
                   f'-N {sta1_nodename} -c ' \
                   f'"replconninfo1 = \'localhost={self.sta1_host} ' \
                   f'localport={remote_port} ' \
                   f'localheartbeatport={remoteheartbeatport} ' \
                   f'localservice={remoteservice} ' \
                   f'remotehost={self.sta1_host} ' \
                   f'remoteport={local_port} ' \
                   f'remoteheartbeatport={localheartbeatport} ' \
                   f'remoteservice={localservice}\'"'
        self.log.info(guc_cmd1)
        guc_res1 = self.common.get_sh_result(self.standby1_node, guc_cmd1)
        self.assertIn('Success to perform gs_guc', guc_res1, 'guc设置失败')

        guc_cmd2 = f'source {macro.DB_ENV_PATH};' \
                   f'gs_guc set -D {self.dn_path} -c ' \
                   f'"listen_addresses=\'localhost,{self.sta1_host}\'"'
        self.log.info(guc_cmd2)
        guc_res2 = self.common.get_sh_result(self.standby1_node, guc_cmd2)
        self.assertIn('Success to perform gs_guc', guc_res2, 'guc设置失败')

        guc_cmd3 = f'source {macro.DB_ENV_PATH};' \
                   f'gs_guc set -D {self.dn_path} -c ' \
                   f'"port=\'{new_port}\'"'
        self.log.info(guc_cmd3)
        guc_res3 = self.common.get_sh_result(self.standby1_node, guc_cmd3)
        self.assertIn('Success to perform gs_guc', guc_res3, 'guc设置失败')

        guc_cmd4 = f'source {macro.DB_ENV_PATH};' \
                   f'gs_guc set -D {self.dn_path} -c ' \
                   f'"local_bind_address=\'{self.sta1_host}\'"'
        self.log.info(guc_cmd4)
        guc_res4 = self.common.get_sh_result(self.standby1_node, guc_cmd4)
        self.assertIn('Success to perform gs_guc', guc_res4, 'guc设置失败')

        guc_cmd5 = f'source {macro.DB_ENV_PATH};' \
                   f'gs_guc set -D {self.dn_path} -c ' \
                   f'"available_zone=\'{available_zone}\'"'
        self.log.info(guc_cmd5)
        guc_res5 = self.common.get_sh_result(self.standby1_node, guc_cmd5)
        self.assertIn('Success to perform gs_guc', guc_res5, 'guc设置失败')

        text = '----step4:build级联备并查询数据库状态 expect:成功----'
        self.log.info(text)
        build_cmd = f'source {macro.DB_ENV_PATH};' \
                    f'gs_ctl build -b standby_full -D {self.dn_path} ' \
                    f'-C "localhost={self.sta1_host} localport={new_port} ' \
                    f'remotehost={self.sta1_host}  remoteport={self.port}" ' \
                    f'-M cascade_standby'
        self.log.info(build_cmd)
        build_res = self.common.get_sh_result(self.standby1_node, build_cmd)
        self.assertIn('server started', build_res, '备机build失败')
        time.sleep(10)

        query_cmd = f'source {macro.DB_ENV_PATH};' \
                    f'gs_ctl query -D {macro.DB_INSTANCE_PATH};'
        self.log.info(query_cmd)
        query_res = self.common.get_sh_result(self.standby1_node, query_cmd)
        self.assertIn('Cascade Standby', query_res, '级联备build失败')

    def tearDown(self):
        text = "----step5:恢复环境 expect:成功----"
        self.log.info(text)
        stop_cmd = f'source {macro.DB_ENV_PATH};' \
                   f'gs_ctl stop -D {self.dn_path}'
        self.log.info(stop_cmd)
        stop_res = self.common.get_sh_result(self.standby1_node, stop_cmd)

        del_cmd = f'rm -rf {self.dn_path};ls {os.path.dirname(self.dn_path)}'
        self.log.info(del_cmd)
        del_res = self.common.get_sh_result(self.standby1_root_node, del_cmd)
        guc_cmd = f'source {macro.DB_ENV_PATH};' \
                  f'gs_guc set -D {macro.DB_INSTANCE_PATH} ' \
                  f'-N {sta1_nodename} -c ' \
                  f'"replconninfo3 = \'\'"'
        self.log.info(guc_cmd)
        guc_res = self.common.get_sh_result(self.standby1_node, guc_cmd)
        restart_cmd = f'source {macro.DB_ENV_PATH};' \
                      f'gs_om -t restart'
        self.log.info(restart_cmd)
        drop_cmd = f"SELECT * FROM pg_drop_replication_slot('{slot_name}');"
        self.log.info(drop_cmd)
        res = self.sta1_comsh.execut_db_sql(drop_cmd, dbname='postgres')
        restart_res = self.common.get_sh_result(self.standby1_node, restart_cmd)
        self.assertIn('server stopped', stop_res, '新build备机数据库停止失败')
        self.assertIn('pg_drop_replication_slot', res, '逻辑复制槽删除失败')
        self.assertIn('Success to perform gs_guc', guc_res, 'guc设置失败')
        self.assertIn('Successfully started.', restart_res, '数据库重启失败')
        self.assertNotIn('dn_path', del_res, '文件删除失败')
        self.log.info(f'----{os.path.basename(__file__)} finish----')
